﻿/*******************************************************************************
 * Copyright © 2016 DJY 版权所有
 * Author: DJY
 * Description: 后台管理系统
 * Website：http://www.djyweb.cn
*********************************************************************************/
using DJY.Code;
using DJY.Service.WorkFlow;
using DJY.Domain.ViewModel;
using DJY.Domain.ViewModel.WorkFlow;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System;
using System.Reflection;
using Newtonsoft.Json;
using System.Xml.Serialization;
using System.Web.Script.Serialization;
using System.ComponentModel;
using System.Dynamic;

namespace DJY.Web.Areas.WorkFlow.Controllers
{
    public class WorkFlowController : ControllerBase
    {
        IWorkFlowEngine engine = OperatorProvider.Resolve<IWorkFlowEngine>();

        /// <summary>
        /// 流程处理
        /// </summary>
        /// <param name="id">流程实例ID</param>
        /// <param name="dev">是否是开发模式</param>
        /// <returns></returns>
        public ActionResult Process(string id,bool dev = false)
        {
            WorkFlowInstance flow = null;
            if(string.IsNullOrEmpty(id))
            {
                flow = new WorkFlowInstance() { error = "流程不存在" };
            }
            else
            {
                string[] ids = id.Split(',');
                if(ids.Length == 2 
                    && !string.IsNullOrEmpty(ids[0])
                    && !string.IsNullOrEmpty(ids[1]))
                {
                    try
                    {
                        flow = engine.GetWorkFlow(ids[0], ids[1], OperatorProvider.GetCurrent()?.UserId);
                    }
                    catch(Exception ex)
                    {
                        flow = new WorkFlowInstance() { error = Code.Common.ShowException(ex) };
                    }
                }

                if(flow == null)
                {
                    flow = new WorkFlowInstance() { error = "流程不存在" };
                }
            }

            flow.dev = dev;
            return View(flow);
        }

        /// <summary>
        /// 流程处理
        /// </summary>
        /// <param name="id">流程实例ID</param>
        /// <returns></returns>
        [HttpPost]
        [AjaxValidateAntiForgeryToken]
        public ActionResult ProcessFlow(ProcessFlowModel flow)
        {
            if (flow == null 
                || string.IsNullOrEmpty(flow.flowId) 
                || string.IsNullOrEmpty(flow.nodeId))
            {
                return Json(new ProcessFlowResult { state = false, msg = "流程不存在" });
            }
            var user = OperatorProvider.GetCurrent();
            flow.userId = user?.UserId;
            return Json(engine.Process(flow));
        }

        /// <summary>
        /// 流程处理待办
        /// </summary>
        /// <param name="id">流程实例ID</param>
        /// <returns></returns>
        public ActionResult ProcessMsg(string id)
        {
            var user = OperatorProvider.GetCurrent();
            return Json(engine.ProcessMsg(id, user?.UserId),JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 流程用户筛选
        /// </summary>
        /// <returns></returns>
        public ActionResult FlowUser()
        {
            var user = OperatorProvider.GetCurrent();
            FlowUserViewModel model = new FlowUserViewModel();
            model.roles = engine.SearchUser(user?.UserId, null, "r");
            model.departs = engine.SearchUser(user?.UserId, null, "d");
            model.posts = engine.SearchUser(user?.UserId, null, "p");
            return View(model);
        }

        /// <summary>
        /// 用户筛选页面
        /// </summary>
        public ActionResult NodeUser()
        {
            return View();
        }

        /// <summary>
        /// 流程条件页面
        /// </summary>
        public ActionResult FlowCondition()
        {
            return View();
        }

        /// <summary>
        /// 我的待办
        /// </summary>
        public ActionResult MyMsg()
        {
            return View();
        }

        /// <summary>
        /// 查询我的消息
        /// </summary>
        public ActionResult SearchMyMsg(WFMessageQueryInfo queryInfo)
        {
            var user = OperatorProvider.GetCurrent();
            if (user != null)
            {
                queryInfo.userId = user.UserId;
                queryInfo.isSys = user.IsSystem;
            }

            return Json(engine.MyMsg(queryInfo));
        }

        /// <summary>
        /// 我的待办
        /// </summary>
        public ActionResult MyMsgList()
        {
            var user = OperatorProvider.GetCurrent();
            return Json(engine.MyMsgList(user?.UserId, 0, 15), JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 查询用户
        /// </summary>
        /// <param name="type">查询类型</param>
        /// <param name="kws">查询关键字</param>
        /// <returns></returns>
        public ActionResult SearchUser(string type, string kws)
        {
            var user = OperatorProvider.GetCurrent();
            if (user == null)
            {
                return Json(new Dictionary<string, string>(), JsonRequestBehavior.AllowGet);
            }

            return Json(engine.SearchUser(user.UserId, kws, type), JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// 流程用户查询
        /// </summary>
        /// <param name="queryInfo">查询条件</param>
        /// <returns></returns>
        public ActionResult SearchFlowUser(FlowWFMessageQueryInfo queryInfo)
        {
            var user = OperatorProvider.GetCurrent();
            if (user == null)
            {
                return Json(new List<FlowUserModel>());
            }

            queryInfo.userId = user.UserId;

            return Json(engine.SearchFlowUser(queryInfo));
        }

        /// <summary>
        /// 验证表达式
        /// </summary>
        /// <param name="condition">表达式</param>
        /// <param name="json">json实体</param>
        /// <returns></returns>
        [ValidateInput(false)]
        public ActionResult CheckCondition(string condition, string json)
        {
            if (string.IsNullOrEmpty(condition))
            {
                return Success("无条件流转恒为True", null);
            }

            Dictionary<string, object> dic = null;
            if(!string.IsNullOrEmpty(json))
            {
                try
                {
                    dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
                }
                catch(Exception ex)
                {
                    return Error("实体Json格式无效："+ex.Message);
                }
            }

            ExpandoObject obj = null;
            if (dic != null)
            {
                obj = new ExpandoObject();
                IDictionary<string, object> oDic = obj as IDictionary<string, object>;
                foreach(KeyValuePair<string,object> kv in dic)
                {
                    oDic.Add(kv);
                }
            }

            try
            {
                bool result = condition.Eval<bool>(obj);
                return Success("计算结果：" + result, null);
            }
            catch (Exception ex)
            {
                return Error("解析表达式失败：" + ex.Message);
            }
        }

        /// <summary>
        /// 获取类字段信息
        /// </summary>
        /// <param name="type">实体类型</param>
        /// <returns></returns>
        public ActionResult ModelKey(string type)
        {
            Dictionary<string, string> keys = new Dictionary<string, string>();
            if (string.IsNullOrEmpty(type))
            {
                return View(keys);
            }
            try
            {
                if (type.IndexOf('.') == -1)
                {
                    type = "DJY.Domain.ViewModel." + type;
                }

                if(type.IndexOf(",") == -1)
                {
                    type += ",DJY.Domain";
                }

                Type t = Type.GetType(type);
                PropertyInfo[] ps = t.GetProperties(BindingFlags.Public
                    | BindingFlags.Instance
                    | BindingFlags.GetProperty
                    | BindingFlags.SetProperty);

                foreach (PropertyInfo pi in ps)
                {
                    if (pi.GetCustomAttribute<JsonIgnoreAttribute>() != null
                        || pi.GetCustomAttribute<ScriptIgnoreAttribute>() != null
                        || pi.GetCustomAttribute<XmlIgnoreAttribute>() != null)
                    {
                        continue;
                    }

                    Type ptype = pi.PropertyType;

                    DescriptionAttribute da = pi.GetCustomAttribute<DescriptionAttribute>();
                    if (da == null)
                    {
                        keys[pi.Name] = string.Empty;
                    }
                    else
                    {
                        keys[pi.Name] = da.Description;
                    }

                    if (ptype.IsGenericType && ptype.GetGenericTypeDefinition() == typeof(List<>))
                    {
                        ResolveListType(pi.Name + "-", ptype.GetGenericArguments()[0], keys);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            return View(keys);
        }

        /// <summary>
        /// 解析列表类型
        /// </summary>
        /// <param name="parentName">父级名称</param>
        /// <param name="type">列表元素类型</param>
        /// <param name="keys">所有的键</param>
        private void ResolveListType(string parentName,Type type,Dictionary<string,string> keys)
        {
            PropertyInfo[] ps = type.GetProperties(BindingFlags.Public
                    | BindingFlags.Instance
                    | BindingFlags.GetProperty
                    | BindingFlags.SetProperty);

            foreach (PropertyInfo pi in ps)
            {
                if (pi.GetCustomAttribute<JsonIgnoreAttribute>() != null
                    || pi.GetCustomAttribute<ScriptIgnoreAttribute>() != null
                    || pi.GetCustomAttribute<XmlIgnoreAttribute>() != null)
                {
                    continue;
                }

                Type ptype = pi.PropertyType;
                DescriptionAttribute da = pi.GetCustomAttribute<DescriptionAttribute>();
                if (da == null)
                {
                    keys[parentName + pi.Name] = string.Empty;
                }
                else
                {
                    keys[parentName + pi.Name] = da.Description;
                }

                if (ptype.IsGenericType && ptype.GetGenericTypeDefinition() == typeof(List<>))
                {
                    ResolveListType(parentName + pi.Name + "-", ptype.GetGenericArguments()[0], keys);
                }
            }
        }
    }
}
